import { defineComponent, onMounted, onUnmounted, onUpdated, ref } from 'vue'

//虚拟列表子项组件
export default defineComponent({
  name: 'VirtualItem',
  props: {
    // 下标
    index: {
      type: Number,
    },
    // 数据源
    source: {
      type: Object,
    },
    // 数据项组件
    component: {
      type: [Object, Function],
    },
    // 唯一标识键值
    uniqueKey: {
      type: [String, Number],
    },
    itemProps: {
      type: Object,
      default: () => {},
    },
    dataPropName: {
      type: String,
      default: 'source',
    },
  },
  emits: ['resizeItem'],
  setup(props, { emit }) {
    const rootRef = ref<HTMLElement | null>(null) // 根节点
    let resizeObserver: ResizeObserver | null = null

    //挂载后
    onMounted(() => {
      if (resizeObserver) {
        resizeObserver = new ResizeObserver(() => {
          dispatchSizeChange()
        })
        //添加观察div
        if (rootRef.value) {
          resizeObserver.observe(rootRef.value)
        }
      }
    })

    onUpdated(() => {
      dispatchSizeChange()
    })

    //卸载后
    onUnmounted(() => {
      resizeObserver?.disconnect()
      resizeObserver = null
    })

    //监听到元素改变
    const dispatchSizeChange = () => {
      const { uniqueKey } = props
      const elementHeight = rootRef.value?.offsetHeight || 0
      emit('resizeItem', uniqueKey, elementHeight)
    }

    const { component: Component, index, source, uniqueKey, itemProps, dataPropName } = props
    const merged = {
      ...itemProps,
      index,
      [dataPropName]: source, // 数据源给到指定属性上
    }
    // 使用类型断言解决类型问题
    return () => {
      return (
        <div key={uniqueKey} ref={rootRef} {...{ index }}>
          {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
          {/* @ts-expect-error */}
          <Component {...merged} />
        </div>
      )
    }
  },
})
